/* vim: set sw=8 ts=8 sts=8 expandtab: */
#ifndef CMAID_VALUE_H
#define CMAID_VALUE_H

/**
 * @addtogroup Cmaid_Value
 * @{
 */
#ifndef FALSE
 /**
  * @def FALSE
  * @brief If not available define @c FALSE
  */
# define FALSE (1 == 0)
#endif

#ifndef TRUE
 /**
  * @def TRUE
  * @brief If not available define @c TRUE
  */
# define TRUE  (1 == 1)
#endif

/**
 * @def CMAID_VALUE_COMPARE_CB(func)
 * @brief Casts a callback to Cmaid_Value_Compare_Cb
 */
#define CMAID_VALUE_COMPARE_CB(func) ((Cmaid_Value_Compare_Cb)(func))
/**
 * @brief Type definition of the compare callback
 */
typedef int (*Cmaid_Value_Compare_Cb)(const void *v1, const void *v2);

/**
 * @def CMAID_VALUE_HASH_CB(func)
 * @brief Casts a callback to Cmaid_Value_Hash_Cb
 */
#define CMAID_VALUE_HASH_CB(func) ((Cmaid_Value_Hash_Cb)(func))
/**
 * @brief Type definition of the hash callback
 */
typedef unsigned int (*Cmaid_Value_Hash_Cb)(const void *v1, unsigned int *nbytes);

/**
 * @def CMAID_VALUE_SIZE_CB(func)
 * @brief Casts a callback to Cmaid_Value_Size_Cb
 */
#define CMAID_VALUE_SIZE_CB(func) ((Cmaid_Value_Size_Cb)(func))
/**
 * @brief Type definition of the aize callback
 */
typedef unsigned int (*Cmaid_Value_Size_Cb)(const void *v);

/**
 * @def CMAID_VALUE_COPY_CB(func)
 * @brief Casts a callback to Cmaid_Value_Copy_Cb
 */
#define CMAID_VALUE_COPY_CB(func) ((Cmaid_Value_Copy_Cb)(func))
/**
 * @brief Type definition of the copy callback
 */
typedef void (*Cmaid_Value_Copy_Cb)(void *dest, const void *src,
                                        unsigned int nbytes);
/**
 * @def CMAID_VALUE_CLONE_CB(func)
 * @brief Casts a callback to Cmaid_Value_Clone_Cb
 */
#define CMAID_VALUE_CLONE_CB(func) ((Cmaid_Value_Clone_Cb)(func))
/**
 * @brief Type definition of the clone callback
 */
typedef void *(*Cmaid_Value_Clone_Cb)(const void *v);

/**
 * @def CMAID_VALUE_FREE_CB(func)
 * @brief Casts a callback to Cmaid_Value_Free_Cb
 */
#define CMAID_VALUE_FREE_CB(func) ((Cmaid_Value_Free_Cb)(func))
/**
 * @brief Type definition of the free callback
 */
typedef void (*Cmaid_Value_Free_Cb)(void *v);

/**
 * @def CMAID_VALUE_STRINGFY_CB(func)
 * @brief Casts a callback to Cmaid_Value_Stringify_Cb
 */
#define CMAID_VALUE_STRINGIFY_CB(func) ((Cmaid_Value_Free_Cb)(func))
/**
 * @brief Type definition of the stringify callback
 */
typedef void (*Cmaid_Value_Stringify_Cb)(const void *v, char *buffer, unsigned int buffer_size);

/** Type definition of the Cmaid_Value structure */
typedef struct Cmaid_Value Cmaid_Value;

/**
 * @brief The value structure
 */
struct Cmaid_Value
{
        Cmaid_Value_Compare_Cb cmp;  /**< for sets, maps and sort */
        Cmaid_Value_Hash_Cb  hash; /**< only called in hash tables */
        int size; /**< the size of the data
                         @arg 0 for pointer, 
                         @arg -1 for variable length
                         */

        /** used if size != 0 */
        struct
        {
                Cmaid_Value_Size_Cb size; /**< only called if size < 0 */
                Cmaid_Value_Copy_Cb copy; /**< if NULL memmove */
                Cmaid_Value_Free_Cb free; /**< if NULL unused */
        } sized;
        
        /** used if size == 0 */
        struct
        {
                Cmaid_Value_Clone_Cb dup; /**< unused if NULL */
                Cmaid_Value_Free_Cb  free; /**< unused if NULL */
        } pointer;
        Cmaid_Value_Stringify_Cb stringify;
};

EAPI extern const Cmaid_Value cmaid_value_pointer;
EAPI extern const Cmaid_Value cmaid_value_inline_string;
EAPI extern const Cmaid_Value cmaid_value_const_string;

EAPI unsigned int cmaid_value_pointer_hash(const void *key, unsigned int *size);
EAPI unsigned int cmaid_value_string_hash(const void *key, unsigned int *size);
EAPI int          cmaid_value_pointer_compare(const void *key1,
                                                const void *key2);
EAPI int          cmaid_value_string_compare(const void *key1,
                                                const void *key2);
EAPI unsigned int cmaid_value_string_size(const void *key);
EAPI void         cmaid_value_pointer_stringify(const void *key, char *buffer,
                                                unsigned int buffer_size);
EAPI void         cmaid_value_string_stringify(const void *key, char *buffer,
                                                unsigned int buffer_size);

/* only for debugging */
void        *cmaid_value_string_dup(const void *key);
void         cmaid_value_string_free(void *key);
/**
 * @}
 */

#endif
